package application.models.datalayer;

/**
 * This class describes general conditions in the form of attributes, operators and values.
 * 
 * @author Philip Rasmussen & Morten Therkildsen
 */
public class DataCondition{
	
	private String attributeName;
	private Object operatorValue;
	private Operator operator;
	
	private int hashCodeCache = 0;
	
	
	/**
	 * Constructs a condition with a specific operator value
	 * @param attributeName The name of the attribute the condition applies to
	 * @param operator An Operator used to express the condition
	 * @param referenceValue The reference value used by the condition. It can be empty/not null if there's no particular value should fulfill.
	 */
	public DataCondition(String attributeName, Operator operator, Object referenceValue){
		
		if(attributeName == null){
			throw new NullPointerException("passed attributeName as null.");
		} else if(operator == null){
			throw new NullPointerException("passed operator as null.");
		}
		
		if(attributeName.trim().length() == 0){
			throw new IllegalArgumentException("passed attributeName as empty.");
		}
			
		this.attributeName = attributeName;
		this.operatorValue = referenceValue;		
		this.operator = operator;
	}
	
	/**
	 * Constructs a DataCondition object
	 * @param attributeName The name of the attribute the condition applies to
	 * @param operator An Operator used to express the condition
	 */
	public DataCondition(String attributeName, Operator operator){
		
		this(attributeName, operator, null);
	}
	
	/** 
	 * Returns the name of the affected attribute
	 * @return The name of the affected attribute
	 */
	public String getAttributeName(){
		
		return attributeName;
	}
	
	/**
	 * Returns the operator used in the condition
	 * @return The operator used in the condition
	 */
	public Operator getOperator(){
		
		return operator;
	}
	
	/**
	 * Returns the reference value for the condition if applicable
	 * @return The reference value for the condition.
	 */
	public Object getReferenceValue(){
		
		return operatorValue;
	}
	
	/**
	 * Checks if the DataCondition object passed to the method has identical fields to the already used DataCondition object.
	 * @param A DataCondition object
	 * @return true if all fields in condition matches all fields in this object.
	 */
	public boolean equals(Object that){
		
		if(that == null || !(that instanceof DataCondition)) return false;
		
		DataCondition condition = (DataCondition) that;
		
		if(
				condition.getAttributeName().equals(attributeName) &&
				condition.getOperator().equals(operator) &&
				(condition.getReferenceValue() == null ? operatorValue == null : condition.getReferenceValue().equals(operatorValue))
			) return true;
		else return false;
	}
	
	/**
	 * We have overridden equals, now we have to do this...
	 * Code found at: http://bytes.com/topic/java/insights/723476-overriding-equals-hashcode-methods
	 */
    public int hashCode() {
    	
        final int multiplier = 23;
        
        if (hashCodeCache == 0) {
        	
            int code = 133;
            
            code = multiplier * code + attributeName.hashCode();
            code = multiplier * code + operator.hashCode();
            code = multiplier * code + (operatorValue == null ? 0 : operatorValue.hashCode());
            hashCodeCache = code;
        }
        
        return hashCodeCache;
    }
}